/* 
 * This program is free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 3 of the License, or 
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
 * for more details.
 * 
 * You should have received a copy of the GNU General Public License along 
 * with this program; if not, write to the Free Software Foundation, Inc., 
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <QSettings>
#include <QListWidgetItem>
#include <QFile>
#include <QDir>
#include <QFileDialog>
#include <QMenu>
#include <QTimer>
#include <QGraphicsProxyWidget>
#include <QMessageBox>
#include <QCompleter>
#include "postitemmodel.h"
#include "imagestorage.h"
#include "imageview.h"
#include "chanmanager.h"
#include "mainwindow.h"
#include "log.h"
#include "extrainfo.h"
#include "extracontainer.h"
#include "imageview.h"
#include "ui_imageview.h"

extern Wishmaster::ImageStorage* g_imagestorage;
ImageViewForm::ImageViewForm(MainWindow* mainform, QWidget* widget) : QWidget(widget),
	m_ui(new Ui::ImageViewForm()), m_prevtab(-1)
{
	m_ui->setupUi(this);
	m_ui->tw_images->removeTab(0);
	m_mainform = mainform;

	QSettings settings;
	m_ui->splitter->restoreState(settings.value("geometry/imageview/splitter").toByteArray());
	m_tags = settings.value("imageview/tags").toStringList();
	QString format = settings.value("imageview/format").toString();
	if(format == "jpg")
		m_ui->rb_jpg->setChecked(true);
	else if(format == "png")
		m_ui->rb_png->setChecked(true);
	else
		m_ui->rb_jpg->setChecked(true);
	hideExtraBox();
	m_savedIcon = QPixmap(":/wishmaster/images/save.png");
	QCompleter* completer = new QCompleter(m_tags);
	m_ui->e_tag->setCompleter(completer);
}

ImageViewForm::~ImageViewForm()
{
}

ImageWidget* ImageViewForm::getImageWidget(const QByteArray& postHid)
{
	ImageWidget* iw = 0;
	for(int i = 0; i < m_ui->tw_images->count(); i++)
	{
		ImageWidget* tiw = static_cast<ImageWidget*>(m_ui->tw_images->widget(i));
		if(tiw->property("posthid").toByteArray() == postHid)
		{
			iw = tiw;
			break;
		}
	}
	return iw;
}

ImageWidget* ImageViewForm::showStaticImage(const QImage& image, const QByteArray& postHid)
{
	log(llDebug, "[static]PostHid: %s", postHid.toHex().data());

	bool createNewTab = false;
	ImageWidget* iw = getImageWidget(postHid);
	if(!iw)
		createNewTab = true;
	if(createNewTab)
		iw = new ImageWidget();
	iw->setStaticImage(image);
	iw->setProperty("posthid", postHid);
	if(createNewTab)
	{
		m_ui->tw_images->addTab(iw, QString::fromUtf8(postHid));
	}

	iw->update();
	hideExtraBox();
	return iw;
}

ImageWidget* ImageViewForm::showAnimatedImage(const QByteArray& arr, const QByteArray& postHid)
{
	log(llDebug, "[animated]PostHid: %s", postHid.toHex().data());

	ImageWidget* iw = getImageWidget(postHid);
	bool createNewTab = false;
	if(!iw)
		createNewTab = true;
	if(createNewTab)
		iw = new ImageWidget();
	iw->setAnimatedImage(arr);
	iw->setProperty("posthid", postHid);
	if(createNewTab)
		m_ui->tw_images->addTab(iw, QString::fromUtf8(postHid));
	hideExtraBox();
	return iw;
}

void ImageViewForm::update()
{
	ImageWidget* iw = dynamic_cast<ImageWidget*>(m_ui->tw_images->currentWidget());
	if(iw)
		iw->update();
}

void ImageViewForm::setExtraContainer(const Wishmaster::ExtraContainer& cont, const QByteArray& posthid)
{
	ImageWidget* iw = getImageWidget(posthid);
	if(iw)
	{
		iw->setExtraContainer(cont);
		ImageWidget* currentiw = dynamic_cast<ImageWidget*>(m_ui->tw_images->currentWidget());
		if(currentiw && currentiw == iw)
			fillExtra(cont);
	}
}

void ImageViewForm::close_click()
{
	tabClose(m_ui->tw_images->currentIndex());
	if(m_ui->tw_images->count() == 0)
		close();
}

void ImageViewForm::saveandclose_click()
{
	save_click();
	close_click();
}

void ImageViewForm::viewByID(int id)
{
	QString type = g_imagestorage->getImageType(id);
	ImageWidget* iw = 0;
	if(type != ".gif")
	{
		QImage pix = g_imagestorage->getImage(id);
		iw = showStaticImage(pix, QString::number(id).toUtf8());
	}
	else
	{
		QFile file(g_imagestorage->getPathForID(id));
		if(!file.open(QIODevice::ReadOnly))
		{
			log(llWarning, "Unable to open file: %s", qPrintable(file.fileName()));
			return;
		}
		QByteArray arr = file.readAll();
		iw = showAnimatedImage(arr, QString::number(id).toUtf8());
	}
	update();
	QStringList l = g_imagestorage->getTagsForID(id);
	m_ui->list_tags->clear();
	m_ui->list_tags->addItems(l);
	m_ui->gb_format->setEnabled(false);
	iw->setSaved(true);
}

Ui::ImageViewForm* ImageViewForm::getUI()
{
	return m_ui;
}

void ImageViewForm::zoom_click()
{
	ImageWidget* iw = dynamic_cast<ImageWidget*>(m_ui->tw_images->currentWidget());
	if(iw)
		iw->zoom();
}

void ImageViewForm::unzoom_click()
{
	ImageWidget* iw = dynamic_cast<ImageWidget*>(m_ui->tw_images->currentWidget());
	if(iw)
		iw->unzoom();
}

void ImageViewForm::save_click()
{
	ImageWidget* iw = dynamic_cast<ImageWidget*>(m_ui->tw_images->currentWidget());
	if(iw)
	{
		QString format;
		QSettings settings;
		if(!iw->isAnimated())
		{
			if(m_ui->rb_jpg->isChecked())
				format = ".jpg";
			else if(m_ui->rb_png->isChecked())
				format = ".png";
			else
				format = ".jpg"; // Default
		}
		else
		{
			format = ".gif";
		}

		int id = iw->imageId();
		if(id == 0)
		{
			QDateTime now = QDateTime::currentDateTime();
			QString filename = QString::number(now.toTime_t()) + QString::number(now.time().msec());

			if(!iw->isAnimated())
			{
				id = g_imagestorage->addImage(iw->image(),  filename + format);
			}
			else
			{
				id = g_imagestorage->addImage(iw->array(), filename + format);
			}
			if(id < 0)
				QMessageBox::information(this, tr("Message"), tr("Image is already in database"));
			iw->setImageId(id);
		}

		g_imagestorage->clearTagsForID(id);
		for(int i = 0; i < m_ui->list_tags->count(); i++)
		{
			QString tag = m_ui->list_tags->item(i)->text();
			if(!tag.simplified().isEmpty())
			{
				tag.replace(' ', '_');
				g_imagestorage->addTagForID(id, tag);
			}
		}

		for(int i = 0; i < m_ui->list_tags->count(); i++)
		{
			m_tags.removeOne(m_ui->list_tags->item(i)->text());
			m_tags.prepend(m_ui->list_tags->item(i)->text());
		}
		iw->setSaved(true);
		m_ui->tw_images->setTabIcon(m_ui->tw_images->currentIndex(), m_savedIcon);

		m_ui->list_fut->clear();
		m_ui->list_fut->addItems(m_tags);
	}
}

void ImageViewForm::addTag()
{
	QListWidgetItem* item = new QListWidgetItem(m_ui->list_tags);
	item->setText(m_ui->e_tag->text());
	item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
	m_ui->list_tags->addItem(item);
	QTimer::singleShot(0, this, SLOT(emptyTagLine()));
}

void ImageViewForm::emptyTagLine()
{
	m_ui->e_tag->setText("");
}

void ImageViewForm::fut_click(QListWidgetItem* item)
{
	m_ui->list_tags->addItem(item->text());
	m_ui->list_fut->model()->removeRow(m_ui->list_fut->row(item));
	m_ui->list_fut->selectionModel()->clearSelection();
}

void ImageViewForm::closeEvent(QCloseEvent* event)
{
	QSettings settings;
	settings.setValue("geometry/imageview/splitter", m_ui->splitter->saveState());
	settings.setValue("imageview/tags", m_tags);
	QWidget::closeEvent(event);
}

void ImageViewForm::saveAsFile()
{
	ImageWidget* iw = dynamic_cast<ImageWidget*>(m_ui->tw_images->currentWidget());
	if(iw)
	{
		if(!iw->isAnimated())
		{
			QString s = QFileDialog::getSaveFileName(this, tr("Save file"), "", tr("PNG Image (*.png);; JPG Image (*.jpg)"));
			if(!s.endsWith(".png") && !s.endsWith(".jpg"))
				s.append(".jpg");
			QImage pic = iw->image();
			pic.save(s);
		}
		else
		{
			QString s = QFileDialog::getSaveFileName(this, tr("Save file"), "", tr("GIF Animation (*.gif)"));
			if(!s.endsWith(".gif"))
				s.append(".gif");
			QByteArray arr = iw->array();
			QFile file(s);
			file.open(QIODevice::WriteOnly);
			file.write(arr);
		}
	}
}

void ImageViewForm::showEvent(QShowEvent* event)
{
	m_ui->list_fut->clear();
	m_ui->list_fut->addItems(m_tags);
}

void ImageViewForm::tagContextMenu(const QPoint& p)
{
	QList<QAction*> actions;
	if(m_ui->list_tags->indexAt(p).isValid())
	{
		actions.append(m_ui->actionDelete_Tag);
    }
	if(actions.count() > 0)
		QMenu::exec(actions, m_ui->list_tags->mapToGlobal(p));
}

void ImageViewForm::deleteTag()
{
	m_ui->list_tags->model()->removeRow(m_ui->list_tags->currentRow());
}

void ImageViewForm::viewByPath(const QString& path)
{
	log(llDebug, "viewByPath");
	if(!path.endsWith(".gif", Qt::CaseInsensitive))
	{
		QImage image;
		if(image.load(path))
			showStaticImage(image, path.toUtf8());
	}
	else
	{
		QFile file(path);
		if(!file.open(QIODevice::ReadOnly))
			return;
		QByteArray arr = file.readAll();
		showAnimatedImage(arr, path.toUtf8());
	}
}

void ImageViewForm::hideExtraBox()
{
	m_ui->gb_extras->hide();
}

void ImageViewForm::showExtraBox()
{
	m_ui->gb_extras->show();
}

void ImageViewForm::extraSave(QModelIndex index)
{
	ImageWidget* iw = dynamic_cast<ImageWidget*>(m_ui->tw_images->currentWidget());
	if(iw)
	{
		if(!index.isValid())
			return;
		// index.row() shows the position in the extraList(), so we have to obtain it first
		Wishmaster::ExtraContainer cont = iw->extraContainer();
		QStringList extras = cont.extraList(); 
		Wishmaster::ExtraInfo extra = cont.extra(extras.at(index.row()));
		QString filename = QFileDialog::getSaveFileName(this, tr("Save file"), "", tr("%1 (*.%2)").arg(extra.type).arg(extra.fileext));
		if(!filename.endsWith(extra.fileext))
			filename.append(".").append(extra.fileext);
		QFile file(filename);
		if(file.open(QIODevice::WriteOnly))
		{
			file.write(extra.data);
			file.close();
		}
	}
}

void ImageViewForm::tabChanged(int i)
{
	m_ui->list_tags->clear();
	ImageWidget* previw = dynamic_cast<ImageWidget*>(m_ui->tw_images->widget(m_prevtab));
	if(previw)
	{
		QStringList l;
		for(int j = 0; j < m_ui->list_tags->count(); j++)
			l.append(m_ui->list_tags->item(j)->text());
		previw->setTags(l);
	}
	ImageWidget* iw = dynamic_cast<ImageWidget*>(m_ui->tw_images->currentWidget());
	if(iw)
	{
		QStringList l = iw->tags();
		m_ui->list_tags->addItems(l);

		fillExtra(iw->extraContainer());
		m_prevtab = i;
	}
}

void ImageViewForm::fillExtra(const Wishmaster::ExtraContainer& cont)
{
	bool showBox = false;
	m_ui->lw_extras->clear();
	QStringList l = cont.extraList();
	foreach(QString s, l)
	{
		Wishmaster::ExtraInfo info = cont.extra(s);
		if(!info.saveable)
			continue;
		showBox = true;
		if(!info.type.isEmpty())
			m_ui->lw_extras->addItem(info.type);
		else
			m_ui->lw_extras->addItem(info.id);
	}

	if(showBox)
		showExtraBox();
	else
		hideExtraBox();
}

void ImageViewForm::tabClose(int i)
{
	ImageWidget* iw = dynamic_cast<ImageWidget*>(m_ui->tw_images->widget(i));
	if(iw)
	{
		/*if(!iw->isSaved())
		{
			if(QMessageBox::question(this,
						tr("Confirm"),
						tr("Image is not saved. Close nevertheless?"),
						QMessageBox::Ok | QMessageBox::Cancel)
					!= QMessageBox::Ok)
				return;
		}*/
		m_ui->tw_images->removeTab(i);
		delete iw; // UDOLIL!!!!!!
	}
}

bool ImageViewForm::event(QEvent* event)
{
	if(event->type() == QEvent::LanguageChange)
	{
		m_ui->retranslateUi(this);
		return true;
	}
	return QWidget::event(event);
}

bool ImageViewForm::hidExists(const QByteArray& postHid)
{
	ImageWidget* iw = getImageWidget(postHid);
	return iw != 0;
}

void ImageViewForm::tagChanged(const QString& tag)
{
	if(tag.isEmpty())
		m_ui->b_addTag->setEnabled(false);
	else if(!m_ui->b_addTag->isEnabled())
		m_ui->b_addTag->setEnabled(true);
}

